﻿using System;
using System.Collections.Generic;
using System.Xml;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using SolutionExtender.AppCode;
using SolutionExtender.Controls;
using SolutionExtender.Interfaces;

namespace McTools.SolutionExtender.DuplicateDetectionRulePlugin
{
    /// <summary>
    /// Allows export / import of Duplicate Detection Rules in Microsoft
    /// Dynamics CRM 2011
    /// </summary>
    public class DuplicateDetectionRuleConnector : IConnector
    {
        #region Variables

        /// <summary>
        /// IOrganization service to access CRM 2011 data
        /// </summary>
        private readonly IOrganizationService _service;

        #endregion Variables

        #region Constructor

        /// <summary>
        /// Initializes a new instance of class DuplicateRuleConnector
        /// </summary>
        /// <param name="service">IOrganization service to access CRM 2011 data</param>
        public DuplicateDetectionRuleConnector(IOrganizationService service)
        {
            _service = service;
        }

        #endregion Constructor

        #region Properties

        public string ObjectName
        {
            get { return "Duplicate detection rule"; }
        }

        public string Description
        {
            get { return "Allows to export Duplicate Detection Rules"; }
        }

        #endregion Properties

        #region Methods

        public List<ImportResult> Import(XmlNode data)
        {
            var ddRule =
                (DuplicateDetectionRule)XmlSerializerHelper.Deserialize(data.OuterXml, typeof(DuplicateDetectionRule));

            var rule = new Entity("duplicaterule");
            rule["baseentityname"] = ddRule.BaseEntityName;
            rule["description"] = ddRule.Description;
            rule["iscasesensitive"] = ddRule.IsCaseSensitive;
            rule["matchingentityname"] = ddRule.MatchingEntityName;
            rule["name"] = ddRule.Name;
            rule["excludeinactiverecords"] = ddRule.ExcludeInactiveRecords;
            rule.Id = ddRule.RecordId;

            if(rule.Id == Guid.Empty)
                rule.Id = _service.Create(rule);
            else
            {
                try
                {
                    _service.Retrieve("duplicaterule", rule.Id, new ColumnSet());
                    _service.Update(rule);

                    var qba = new QueryByAttribute("duplicaterulecondition");
                    qba.Attributes.Add("regardingobjectid");
                    qba.Values.Add(rule.Id);
                    qba.ColumnSet = new ColumnSet(true);

                    foreach(var condition in _service.RetrieveMultiple(qba).Entities)
                    {
                        _service.Delete(condition.LogicalName, condition.Id);
                    }
                }
                catch
                {
                    rule.Id = _service.Create(rule);
                }
            }

            foreach (var condition in ddRule.Conditions)
            {
                condition.RegardingObjectId = new EntityReference("duplicaterule", rule.Id);

                var conditionRule = new Entity("duplicaterulecondition");

                conditionRule["baseattributename"] = condition.BaseAttributeName;
                conditionRule["matchingattributename"] = condition.MatchingAttributeName;
                conditionRule["operatorcode"] = condition.OperatorCode;
                conditionRule["ignoreblankvalues"] = condition.IgnoreBlankValues;

                if (condition.OperatorCode.Value == 1 || condition.OperatorCode.Value == 2)
                {
                    conditionRule["operatorparam"] = condition.OperatorParam;
                }

                conditionRule["regardingobjectid"] = condition.RegardingObjectId;

                _service.Create(conditionRule);
            }

            return null;
        }

        public IExportControl GetExportControl(IOrganizationService service)
        {
            return new DuplicateDetectionRuleControl(_service);
        }

        public string GetRecordName(XmlNode node)
        {
            return node.SelectSingleNode("Name").InnerText;
        }

        #endregion Methods
    }
}
